package io.task.message.socket;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;
import java.nio.channels.CompletionHandler;

@Slf4j
@Setter
@Getter
public class ReadCompletionHandler implements CompletionHandler<Integer, ByteBuffer> {

    private ChannelContext channelContext = null;
    private ByteBuffer readByteBuffer;


    public ReadCompletionHandler(ChannelContext channelContext) {
        this.channelContext = channelContext;
        this.readByteBuffer = ByteBuffer.allocate(channelContext.getReadBufferSize());
        this.readByteBuffer.order(Config.byteOrder);
    }

    @Override
    public void completed(Integer result, ByteBuffer byteBuffer) {
        if (result > 0) {
            channelContext.stat.latestTimeOfReceivedByte = System.currentTimeMillis();
            readByteBuffer.flip();
            channelContext.decodeRunnable.addMsg(ByteBufferUtils.copy(readByteBuffer));
            channelContext.decodeRunnable.execute();
            if (IoUtils.checkBeforeIO(channelContext)) {
                read();
            }

        } else if (result == 0) {
            log.error("{}, 读到的数据长度为0", channelContext);
            Io.close(channelContext, null, "读到的数据长度为0", ChannelContext.CloseCode.READ_COUNT_IS_ZERO);
            return;
        } else if (result < 0) {
            if (result == -1) {
                Io.close(channelContext, null, "对方关闭了连接", ChannelContext.CloseCode.CLOSED_BY_PEER);
                return;
            } else {
                Io.close(channelContext, null, "读数据时返回" + result, ChannelContext.CloseCode.READ_COUNT_IS_NEGATIVE);
                return;
            }
        }
    }

    @Override
    public void failed(Throwable exc, ByteBuffer byteBuffer) {
        Io.close(channelContext, exc, "读数据时发生异常: " + exc.getClass().getName(), ChannelContext.CloseCode.READ_ERROR);
    }

    private void read() {
        if (readByteBuffer.capacity() == channelContext.getReadBufferSize()) {
            readByteBuffer.position(0);
            readByteBuffer.limit(readByteBuffer.capacity());
        } else {
//			log.error("动态调整了readbuffersize, 原:{} / 新:{}", readByteBuffer.capacity(), channelContext.getReadBufferSize());
            readByteBuffer = ByteBuffer.allocate(channelContext.getReadBufferSize());
        }

        channelContext.asynchronousSocketChannel.read(readByteBuffer, readByteBuffer, this);
    }


}
